﻿#region MIT License

//The MIT License (MIT)
//Copyright (c) 2013 PTA GmbH
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
//to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
//and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xrm.Sdk;
using Pta.TrueUniqueAutonumberCreator.Plugins.SequenceService;

namespace Pta.TrueUniqueAutonumberCreator.Plugins
{
    /// <summary>
    ///     Implements the true unique autonumber creator functionality as a MS CRM 2011 plugin
    ///     This is pre operation synchronous plugin registered with the "Create" SDK message on every entity (a step is defined for).
    ///     The plugin conntect to public available internet web service for querying a true global unique number.
    ///     Then this number (combined with the bucketname) is stored in a configurable field of the entity.
    /// </summary>
    /// <author>Hendrik Saly (PTA GmbH)</author>
    public sealed class TrueUniqueAutonumberCreatorPlugin : Plugin
    {
        /// <summary>
        ///     Constructor of the plugin
        ///     See http://gonzaloruizcrm.blogspot.de/2011/09/adding-configuration-to-plugins-in-crm.html
        /// </summary>
        public TrueUniqueAutonumberCreatorPlugin(string unsecureConfig, string secureConfig)
            : base(unsecureConfig, secureConfig)
        {
            RegisteredEvents.Add(
                new Tuple<int, string, string, Action<LocalPluginContext>>((int) PluginStage.PreOperation, "Create",
                                                                           null, OnCreate));
        }

        private void OnCreate(LocalPluginContext localContext)
        {
            localContext.TracingService.Trace("OnCreate() entered");

            Dictionary<string, string> kvs = ParseKeyValueString(UnsecureConfig);
            string bucketname = kvs["bucketname"];
            string apikey = kvs["apikey"];
            string autonumberattribute = kvs["autonumberattribute"];
            int startvalue = 0;

            localContext.TracingService.Trace("bucketname: {0}, apikey: {1}, autonumberattribute: {2}", bucketname,
                                              apikey, autonumberattribute);

            var target = ((Entity) GetTarget(localContext));

            //if the autonumber field ist not empty (e.g. was manually filled by the user) do not overwrite this value and do not assign a autonumber
            if (target.Attributes.ContainsKey(autonumberattribute) &&
                !string.IsNullOrEmpty((string) target[autonumberattribute]))
            {
                //graceful quit
                return;
            }


            if (kvs.ContainsKey("startvalue"))
            {
                int.TryParse(kvs["startvalue"], out startvalue);
            }

            localContext.TracingService.Trace("startvalue: {0}", startvalue);

            //get the nex unique number from the webservice
            int nextValue = GetNextValue(bucketname, apikey, startvalue);

            string nextValueString = Convert.ToString(nextValue);

            localContext.TracingService.Trace("next value: {0}", nextValueString);

            //store the retrieved unique number (prefixed with the bucketname) and padded with trailing zeros to the autonumberfield of the entity
            target[autonumberattribute] = bucketname + "-" + nextValueString.PadLeft(10, '0');

            localContext.TracingService.Trace("OnCreate() end");
        }


        private int GetNextValue(string bucketname, string apikey, int startValue)
        {
            var sequenceService = new DBSequenceService();
            
            //set custom web service url
            //sequenceService.Url = "http://ptahs1.cloudapp.net/DBSequenceService.svc";
           
            long[] nextnumbers = sequenceService.GetNextNumbersAndInitialize(bucketname, apikey, startValue, true, 1, true);
            return (int) nextnumbers[0];
        }

        //Parse a string like key1=value1;key2=vlaue2;key3=value3; ...into a Dictionary
        //Delimters are ; and CRLF
        private Dictionary<string, string> ParseKeyValueString(string input)
        {
            var retVal = new Dictionary<string, string>();

            if (string.IsNullOrEmpty(input)) return retVal;

            input.Split(";\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
                 .Select(kv => kv.Trim())
                 .ToList().ForEach(kv => retVal.Add(kv.Split('=')[0], kv.Split('=')[1]));

            return retVal;
        }
    }
}